JAWS Macro Instruction Manual
March 11, 1997
Version 1.0

Synopsis:
This is a working document that will be updated as changes occur to the JAWS
product.  It is current as of the above date

Introduction
This book contains all the information you will need to know in order to write
your own macros.  If you don't know what a macro is, don't worry, as we'll
explain that too.  The following is a list of sections with a brief description of
what's in each:

1. "Introduction" explains what macros are, how they modify JAWS
activities and why macro files are needed.
2. "Our First Macro" helps you to create a simple macro file, compile it
and load it so that you can gain a little confidence.
3. "Basics" describes how the JAWS macro system works, the difference
between the default macro and application macros and how they work
together.
4. "Creating Simple Macros" teaches macro writing on a small scale.  It
is intended for those who want to tweak the existing macros and create
keys to read textual information from the screen.
5. "Creating Complex Macros" is a more in-depth study of the art of
macro writing.  It is intended for those who want to learn to write
more elaborate macros.

What are Macro Files
A macro is a small computer program that modifies JAWS for a specific
situation.  Suppose that you are using an application program that provides a
description of each menu item at the bottom of its window.  A sighted user just
glances down to see that information whenever she doesn't know what a
particular menu item does.  Sure, you can turn on the JAWS Cursor, go to the
bottom of the window and read the line, but wouldn't it be easier if you could
just press a key to read the help text?  Or even better, how about if JAWS could
read it automatically and of course you want to be able to turn that on and off.
JAWS is always under control of macros.  When you press Insert+Up Arrow to
read the current line, it activates a macro that knows how to read the current
line correctly depending on the current cursor in use.  No doubt you recall
hearing the JAWS start-up messages about how to get various kinds of help.
You guessed it!  That comes from a macro called AutoStart that runs whenever
JAWS starts up.

JAWS provides you with all the tools you need to modify and create macros.
The Macro Editor has built in capabilities to create macros, insert functions,
display reference information, check for errors and save your macro file.

Why Do We Need Macros?
That's a good question.  Why not just build all the standard things into JAWS
and not have macros?  Here are a couple of really good reasons:
*  Not all application programs follow the standard structures for programs.
Big surprise!  Sometimes macros are needed just for JAWS to understand
how to deal with a particular screen.
*  Just to make you more efficient.  Let's say you work as an airline
reservations agent.  When you type in the customer's destination, the
system responds with flight information to that destination.  JAWS cannot
know where that will be, but a macro can.  Once again, you can remember
where that information is displayed and go read that area, but that takes
time.  The quicker you perform, the more productive you are.  We all know
where that goes.

Our First Macro
Now let's write a small macro that has JAWS speak our name on demand.
Follow these steps exactly and you will see that writing simple macros is not
all that hard:

1. If you do not already have JAWS for Windows running, start it.
2. Focus on the JFW Window by pressing Insert+J.
3. Pull-down the Utilities Menu by pressing Alt+U.
4. Select the Macro Editor by pressing M.  Then make sure you are in PC
Cursor.
5. Start a new macro by pressing CTRL+A and you should hear a help
message that says to type in the name of your macro.  The editor has
already created a line for the beginning of the macro and another for the
end.  The macro beginning line looks like the following:
MacroBegin {}
and the cursor is placed between the braces, which is where the name of
your macro goes.
6. Type in the name of our macro exactly as it appears on the next line:
Control+Shift+F1
7. The name of our macro is the key sequence that will run it.  Pressing
Control + Shift + F1 will make our macro run.
8. Press Down Arrow to position the cursor at the blank line between the
macro beginning and the macro ending.  This is the line where we will
place our actual macro code.
9. We want JAWS to speak a string of characters, so we will use a function
called SayString.  Note that there is no space in the function name.
Computer functions are often named by putting a couple of words together
that describes the function.  We will then give SayString its parameter.  A
parameter is simply something that your code passes along to the function.
Imagine that!  Now you know what programmers mean when they talk
about passing parameters.  Our parameter is the phrase that we want
spoken.  Type your code line exactly as it appears on the next line except
that you might want to substitute your own name as your name is probably
not Frank:
SayString ("My name is Frank")
10. You should now have the following three lines on your page exactly as they
appear in this step and nothing else on the page.  Remember that close is
not good enough as computers expect us to be to the letter.
MacroBegin {Ctrl+Shift+F1}
SayString ("My name is Frank")
MacroEnd
11. Now we need to save our work.  Press Alt + F to pull-down the file menu,
arrow down to the Save As selection and press enter.  This action opens the
Save As Dialog box with the cursor placed at the file name field.
12. The suggested file name is UNTITLED.JMS.  Change it to TEST1.JMS.
We use the extension JMS to tell JAWS that this is a JAWS Macro Source
file.  Congratulations!  You have just written your first macro code.  Now
we need to find a way to use it.  Macro files usually are given the name of
the program that they are written for, but we want ours to always be
available.  Therefore, we will include it in with the default macro file.
13. Now open the default macro file.  Pay close attention as this part is a bit
tricky.  There are two of these default macros depending on whether you
are on a laptop or a desktop.  It's different because the default keys are
different on different types of keyboards.  Start by pressing Control + O to
get the file open dialog box.
14. The cursor is placed in the file name edit field.  Type in either
jfw_desk.jms for a desktop system or
jfw_lap.jms for a laptop system
and press enter to open the default macro file.
15. Make sure that you are in PC Cursor mode.  Start moving down a line at a
time by pressing Down Arrow until you find a line that begins with the
word, include.  There will be several of these lines in a row.  Keep moving
down until you hear a blank line and stop.  Type in the following line:
Include "test1.jms"
and press enter.  We have just told JAWS that we want our test macro
included in with the other
default macros.
16. Now we must recompile the default macro file.  Press Control + S to save
and compile the default macro file.  If all goes well, you hear a message
spoken saying that compile is complete.  If you hear an error message, it
means that you have typed something wrong either in TEST1.JMS or the
default macro file.  Go back through the previous steps and try again.
When you have a completed compile, continue with the next step.
17. Press our key sequence, Control + Shift + F1 to hear our string spoken.
How about that!  Your first macro.
18. Now close the Macro Editor by pressing Alt + F4.

Basics
JAWS is always under control of some macros.  The term, macro can be
confusing as a macro file is made up of a group of individual macros, but users
often refer to a macro file without the word file.  We'll try not to do that in
this document.  The default macro file is loaded when JAWS starts and is always
active in all sessions.  You can think of macro files as "stacked" with the
default on the bottom of the stack.  An application macro file is stacked on top
of the default when its application loads.  JAWS knows to do this because the
application macro file name is the same as the application program.  Let's go
over the default and application macro files separately.

Default Macro File
The default macro file is actually a group of several macro files.  It contains
most of the keys that you use regularly and it monitors a number of system
events for you.  For instance, when you press Insert + Up Arrow, the default
macro file contains the commands that read the current line properly.  It also
knows when you open a new program and speaks the title of its window for
you.

Application Macro Files
Application macro files contain special macros that make it easier to use the
application.  Remember that application macro files are stacked on top of the
default which means that you can use the functions of both.  The application
macro file has precedence.  That means that JAWS looks in the application
macro file first.  If there are duplicate keys in the application and default
files, the application file is used.  Sometimes a macro writer will duplicate a
standard key in his application macro so that he can add some special stuff just
for this application, but not force the user to learn a new key.

This is the end of the basics section.  By now you should be getting a mental
picture of why we need macros and how JAWS uses them to improve your
efficiency.  The next two sections are titled "Creating Simple Macros" and
"Creating Complex Macros."  If you want to learn to create macros to read
textual information from the screen, then continue with the next section.  Those
who want to learn to do complex macros that involve dealing with windows
structure, using programming constructs and manipulating JAWS settings should
skip the next section and continue with "Creating Complex Macros."

Creating Simple Macros
A simple macro is one in which you might select a cursor, move to a specific
point in the window and then read the text.  In this section, we'll go over how
to create macros that do those things..
Individual Macro Structure
Remember that a macro file is made up of one or more macros.  A macro must
have the following pieces in this exact order:

1. The macro begin command.  This is simply the word, MacroBegin.
2. On the same line as the MacroBegin command, there is something
enclosed in braces.  Place what triggers the macro in between the braces.
For instance, MacroBegin {Insert+Q} means that this macro runs
whenever the user presses Insert + Q.
3. Then you put in all of the functions that you need in sequential order.  This
could be as simple as just saying a string as we did in "Our First Macro" or
several functions together.
4. The macro end command, MacroEnd, is always the last line of  a macro.

Using Macro Functions
Now, let's go over some of the commonly used functions for getting around and
reading text.

Reading Text
Here are some functions to read text from the screen.
SayCharacter() - Reads the character located at the position of the active
cursor.
SayWord() - Reads the word located at the position of the active cursor.
SayLine() - Reads a line of text where the active cursor is located.
SayString() - Speaks some text that you put in between its parentheses.
Enclose the text in double quotes.

Selecting and Moving Cursors
Before you attempt to read something from the screen with a macro, it's
important to understand about cursors.  Just from using JAWS you know that
there are two kinds of cursor: PC and JAWS.  The PC cursor is usually where
characters would be placed when you type.  However, when you are using a
menu or tabbing through some selections, think of the PC cursor as the "visual
focus."  We spend most of our time using PC cursor, but you know that when
you need to read other areas of a window, you switch to JAWS cursor.  When
we use the JAWS cursor, it is not restricted and can go anywhere and read any
text on the screen.  You probably also know that the JAWS cursor always
moves the mouse pointer along with it.  There is actually a third kind of cursor
called the Invisible cursor.  It is just like the JAWS cursor as its movement is
not restricted, but it does not bring the mouse pointer with it.  What do we do
with these cursors and why?

The PC cursor belongs to our computer and so we should not be moving it around
with a macro.  There are also many places on the screen where the PC cursor
cannot go like the title of a window or the status bar.  Therefore, before we go
to read some text from the screen, we should first switch to one of the other
cursors, but which one?  Here's a rule of thumb.  If we plan to stay at the new
position and read around, then we should use the JAWS cursor.  Then all of the
JAWS cursor commands are available and we can click with the mouse.  If our goal
is to go read something and return to the present position, then use the
invisible cursor.  There is also a save and restore function that you can use to
put everything back as it was before our macro.

Here is a list of the functions that you can use to select and manipulate the
cursors:
PcCursor() - Activates the PC Cursor.
JAWSCursor() - Activates the JAWS Cursor.
InvisibleCursor() - Activates the Invisible Cursor.
RoutePCtoJAWS() - Moves the PC Cursor to the JAWS Cursor, if possible.
RouteJAWStoPC() - Moves the JAWS Cursor to the PC Cursor.
RouteJAWSto Invisible() - Moves the JAWS Cursor to the Invisible Cursor.
RouteInvisibletoPC() - Moves the Invisible Cursor to the PC Cursor.
RouteInvisibletoJAWS() - Moves the Invisible Cursor to the JAWS Cursor.
SaveCursor() - Remembers the active cursor and its position.
RestoreCursor() - Reactivates the saved cursor and position.

The next group of functions move the cursor.
PriorCharacter() - Moves the active cursor to the prior character.
PriorWord() - Moves the active cursor to the prior word.
PriorLine() - Moves the active cursor to the prior line.
NextCharacter() - Moves the active cursor to the next character.
NextWord() - Moves the active cursor to the next word.
NextLine() - Moves the active cursor to the next line.
JAWSHome() - Moves the active cursor to the beginning of the line.
JAWSEnd() - Moves the active cursor to the end of the line.
JAWSPageUp() - Moves the active cursor to the top of the window.
JAWSPageDown() - Moves the active cursor to the bottom of the window.
Note that you would usually follow a move function with a read function.
Creating Reading Macros
Now, let's look at a practical use of what we have learned so far.  Before we
look at a real macro, here's the steps again:

1. First, select a cursor.
2. Now move your selected cursor to a specific position in the window.
3. Finally select the appropriate reading command.

The following is the macro we can use to read the bottom line of a window and
we'll show you two variations of it.  There is a comment at the end of each line
that describes the function.  In the first macro we will switch to the JAWS
cursor, read the bottom line and then leave the JAWS cursor active at the bottom
of the window.

MacroBegin{Insert+Page Down} ; Begins the macro and assigns it to the Insert
+ Page Down key
JAWSCursor() ; Select the JAWS cursor
RouteJAWSToPC() ; Move the JAWS cursor to the PC cursor for a starting
point
JawsPageDown() ; Move the invisible cursor to the bottom of the window
JawsHome() ; Move the invisible cursor to the beginning of the bottom line
SayLine() ; Speak the bottom line of the window
MacroEnd ; End of the macro

The next variation adds the save and restore cursor functions and uses the
invisible cursor as we just want to read the line and return to our starting
point.

MacroBegin{Insert+Page Down} ; Begins the macro and assigns it to the Insert
+ Page Down key
SaveCursor()  ; Saves the current cursor and its position
InvisibleCursor() ; Select the invisible cursor
RouteInvisibleToPC() ; Move the invisible cursor to the PC cursor for a starting
point
JawsPageDown() ; Move the invisible cursor to the bottom of the window
JawsHome() ; Move the invisible cursor to the beginning of the bottom line
SayLine() ; Speak the bottom line of the window
RestoreCursor() ; Reset the cursor and position we saved
MacroEnd ; End of the macro

See how it works?  You could use this macro to read the status line in Microsoft
Word.  The status line tells you the page number, line number, column number and
other information like that.  If you only wanted the page number, you would
substitute two SayWord() functions for the SayLine() function.  Then you would
just hear the words:  page and the number.

Putting It All Together
Now let's look at the process of creating a macro, adding it to a macro file and
then recompiling the file so we can use it.  Here's the plan.  We will modify
the macro file for the JAWS Macro Editor to include a key that reads the current
line number.  We'll need the JAWS Macro Editor for this task.  Remember that we
used this editor in section 2 when we created our first macro.  This time, we'll
let the macro editor do some of the work for us.  Follow these steps exactly:

1. Start the JAWS macro editor.  If you don't remember how to do that,
activate the JAWS window with Insert + J, then press Control+M to start
the editor.
2. Now we need to open the macro file for this program.  If you press Insert +
Q, you will find out that the program name for the macro editor is
MACROED.EXE and you also know that the macro file currently in use is
the macro editor macro file.  That means that there is already a macro file
for this application and its name is MACROED.JMS.  We hope that you
remember from section 2 that a macro source file always has the extension
JMS and from section 3 that its name must be the same as the application.
3. Press Control + O to display the File Open dialog box, type
MACROED.JMS in the file name field and press enter to open the file.
4. Before we write our macro, let's explore around to see what we want our
macro to read.  The macro editor has a status line at the bottom that
contains a ready prompt, the current line number and the total number of
lines in the file.  We want to read only the current line number with our
macro.  Just to make sure we know what we want our macro to do, let's do
it manually first.
5. Start by activating the JAWS cursor.
6. The press page down to move to the bottom line and home to move to the
beginning of the line.
7. Now say the current word and you should hear, "ready."  Use the next word
key to read across the line.  You now know that the second word on this
line is the current line number.  We now know what our macro has to do.
Activate a cursor, position it at the proper place and then read the word.
OK, reactivate the PC cursor and we'll get started.
8. Press Control + A to start a new macro.  Don't worry about where your
cursor is as the macro editor will move to the end of the file before
beginning your new macro.
9. Type CONTROL+SHIFT+1 in between the left and right braces.  That will
be the key sequence for our macro.
10. Press down arrow once to get to the blank line between the macro begin
and end commands.  This is where we put our commands.
11. This time we will not type our commands as we did in section 2.  We will
use the Insert Function tool of the editor.
12. Press Control + I to start the Insert Function tool.  The Insert Function
dialog box is displayed and the cursor is placed in the function name field.
13. There is also a list of functions displayed beneath the function name field.
You could tab down to the list and start arrowing through the functions to
find the one you need, but that would not be very efficient as there are
more than two hundred of them.  JAWS has a better way, but it does
require that you have some idea of the function name.
14. Just like in our example earlier, we need to start with saving the cursor and
position.  The function is SaveCursor(), but we only need to press the S as
the Insert Function tool starts searching as soon as you start typing  and
SaveCursor() is the first function that starts with an S.  Notice that as it
focused on SaveCursor(), a help message was also read that explains how
this function is used.
15. Press enter and this function is placed into our macro.  Easy isn't it?  Now
let's activate the invisible cursor.  We use the invisible cursor here as we
just want to read the line number and return.  No sense in dragging the
mouse with us, so we won't use the JAWS cursor.
16. Press enter to insert a new line and then Control + I again.
17. The function we need this time is InvisibleCursor().  We'll have to type two
characters this time as InvisibleCursor() is not the first function that begins
with an I.  Type slowly so that you can hear each function as it is
highlighted.  Once you hear InvisibleCursor(), press enter to place it in our
macro.
18. Use the same procedure to add the rest of our functions in this order:
JawsPageDown(), JawsHome(), NextWord(), SayWord() and
RestoreCursor().
19. Press Control + S to compile the macro file.  If you made no mistakes, you
should hear the compile complete message.  If not, repeat the previous
steps until you can compile without an error.
20. Usually, as soon as the macro file is compiled, we can start using it, but
because it is the macro editor's file, we must close the editor and then
reopen it before our changes are effective.  Do this now.
21. Press Control + Shift + 1 to test to make sure that your macro works as you
intended.  Move the cursor down a few lines and try it again.  You should
hear the new line number announced.

Try a few variations like read the whole line instead of the word.  Then try to
say just the number of lines in the file.  When you feel comfortable with this
process, either continue with the next section, "Creating Complex Macros or
jump in a write that macro you been wanting for some time now.

Creating Complex Macros
This section describes complex macro writing.  It contains the following
subjects:
*  "Windows Program Structure" covers what you need to understand
about the various identifiers and how Windows are arranged in a
hierarchical order.
*  "Building Blocks of the Macro Language" provides details on the
individual constructs that make up macros.  This is where we start to
put things together that will become macros.  We'll also look at when
and how to use the various functions.
*  "Macro Writing Techniques" is where we start putting all this
information to use.  It provides the techniques used in writing complex
macros.  This section also has a lesson on using the JAWS Macro
Editor program.
*  "Debugging" covers how to work out the bugs in your macros along
with some tips that help with the process.

Windows Program Structure
You've probably heard people use terms like window class and window ID in
discussions about how Windows programs are structured.  In this section, we'll
try to explain enough about window hierarchy and structure in order for you to
make use of the macro functions that query and compare these items.  The first
question is what is a window?  Well, that's simple.  Programs run inside of a
window.  Even JAWS has a window.  That's true.  The JAWS window is a
window, but it might surprise you to know that every entry field is also a
window.  Sounds complicated doesn't it?  Let's see if we can sort it out.

Hierarchy
It will all make more sense if we look at the hierarchy of windows in the
system.  The metaphor most often used is one of parents and children.  Here's
how it works.  Your computer desktop is the parent of all application windows.
That makes the JAWS Window, your word processor's window and the Internet
browser's window all children of the desktop.  OK, now let's go to the next
level.  The word processor has several child windows: the text area, the menu
bar, the toolbar and the status line.  Are you beginning to get it?  When you
ask to open a file in the word processor, a child window appears so that you can
look for the file.  It's often referred to as a dialog box, but in the grand
scheme of things, it is a child window to the word processor, its parent.  Now
think of the Open File dialog box as a parent and then you find that the File
Name field is a child window of the dialog.

Identifying Windows
The application programmer assigns a number of identifiers to each window.  For
instance, each has a Window Class and an ID.  The Window Class tells us whether
it is an edit field or a push button.  The ID is a unique identifier that the
programmer uses to mark each window in his program.  No two windows in a program
should have the same ID, but they often do anyway.  Of course, there is no way
to insure that two windows in different programs don't have the same ID.
Therefore, to sort things out, the system assigns a unique identifier, called a
window handle, to every window in the system.  Window handles are numbers, but
we rarely read them and never perform arithmetic operations on them.  Don't
forget that the system assigns these handles as windows are used and so the
handle assigned to a window this time will not be the same tomorrow.  We use the
window's handle to identify it among all of the other windows in the system at
any given time.  We use the window class to identify what type of a window it
is.  Knowing these two bits of information helps to make sure that your macro is
always focused correctly.  There are some built-in default macros that you can
use to query these and other types of information from an application.  We'll
teach you how to use them in "Exploring the Application" later in this section.

Building Blocks of the Macro Language
We construct macro files from the building blocks that make up the JAWS
macro language.  Think of this part of the book as learning a language because
you will be doing exactly that.  Just as our spoken language has parts of speech
that make sentences that make paragraphs, so also does the JAWS macro
language has statements that make macros that make macro files.  First, we'll
learn how an individual macro is assembled, then learn all the different kinds
of statements in this language.  In the next section, "Macro Writing
Techniques" we'll learn how to put complete macro files together, compile and
use them.

The Macro
Remember that a macro file is made up of one or more macros that perform
special functions needed in the current environment.  A macro must have the
following pieces in this exact order:

1. The macro begin command.  This is simply the word, MacroBegin.
2. On the same line as the MacroBegin command, there is something
enclosed in braces.  Place what triggers the macro in between the braces.
For instance, MacroBegin {Insert+Q} means that this macro runs
whenever the user presses Insert + Q.  MacroBegin {FocusChanged} runs
whenever the visual focus changes on the screen.
3. The Statement Sequence is all of the commands and functions that you
want to run.  This could be as simple as just saying a string as we did in
"Our First Macro" or several pages of complex code.
4. The macro end command, MacroEnd, is always the last line of  a macro.

Macros generally fall into one of these groups: AutoStart, key macros and event
macros.  We suggest that you try to group them that way in your macro file.
The following is a description of each type:
*  The AutoStart macro is the initialization for your macro file.  It
automatically runs when the macro file loads and serves as the starting
point for any other activities.
*  Key macros are those that are run whenever a specific key is pressed.
*  Event macros are triggered by an event in the system such as new text
appearing on the screen or the visual focus changing.  Sometimes these
events will "return" information to the macro.  For instance, FocusChange
returns information about the current window and the previous window.
*  Macros may be run as part of other macros.  We'll show you this function
later, but for now it is sufficient to know that if you wanted a reading of the
current line in your macro, you could just have JAWS run the Current Line
macro and the current line would be spoken.

Types of Statements
The following is a list of the types of statements that make up macros.  Each
statement is like a part of speech in the JAWS macro language, has a specific
job to perform, and has certain rules associated with its use.

Comments
Comments are lines of text in your macro file that are not part of actual
statements.  They are usually used to inform those reading the source file how
the statements work.  Comments may be placed on a line by themselves or at
the end of a line.  Begin a comment with a semicolon.  Everything else on the
line after it is treated as a comment.  If you need multiple lines for comments,
start each line with a semicolon.

Includes
The include statement tells the compiler to include another file along with this
file.  Include files usually are separate files with common macros that are used
by a number of macro files, but sometimes a macro writer may break a large macro
file into two more manageable pieces.  In that case the second file would be
added to the first as an include.  Include files usually have the extension,
JMH, in order to separate them from regular macro source files.  The include
statement has the name of the included file in quotes as follows:

Include "Test1.jmh"

The following is a list of the standard include files provided with JAWS:
  HJGLOBAL.JMH - Contains the default JFW global variables.
  HJCONST.JMH - Contains the default JFW constants.
  JFW_KEY1.JMH - Contains the common macros that are used in both the
laptop and PC keyboard layouts.
  JFW_KEY2.JMH - Contains the macros for Braille displays and Dragon
Dictate.
  JFW_KEY3.JMH - Contains help message macros.
  UTILITY.JMH - Contains the macros that provide Windows information
for macro writers.
  JFW_DESK.JMM - Contains the standard message files.
Note: Don't worry, we are about to explain variables, constants and message
files.

Message Files
A message file is a special include file, which assigns numbers to common
messages.  This way the macro writer may use the message number in place of
the message and JAWS will look up the actual text for the message in the
message file.  All of the macro files shipped with JAWS have their own
separate message file.  Use the same name as your macro file when you create
your own message file and give it an extension of .JMM.  Then include  it in
your macro file.

Variables
A variable, as its name implies, is an entity that holds a value that changes
during the code execution.  The term execution is used by programmers to
describe the running of code.  We use it here just to introduce you to the term.
Each variable is of a specific type.  The contents of a variable are stored in
memory by the JAWS program and may be used by your code whenever you
need it.
Variables are "declared" to have a name and a type before they may be used.
Each variable must have a distinct name to distinguish it from other functions
and names used in the code.  Be careful not to use names that are already
assigned to functions, global variables and constants.
The following is a description of the types of variables allowed in the JAWS
macro language:
Integer - A variable designed to hold an integer value.  It is declared like
this:
Int MyVariable
Note that the type is followed by the distinct name assigned to this
variable.
String - Holds a string of characters.  A string is a group of characters
including spaces.  It is declared like this:
String MyVariable
Handle - Holds a window handle.  A window handle is a unique number
assigned to each window in a currently running program.  It is declared
like this:
Handle MyVariable

Global vs. Local Variables
Variables may be local which means they may only be used in the macro where
they are declared or global which means that they may be used in any macro.
Global variables are declared at the beginning of a macro file with the group
heading, Globals.  Place this group next after the include statements.  Local
variables are declared within a macro in the next statement after the
MacroBegin.  They have the heading, Var.  Here's how each looks in an
example from a standard macro file:
The following declaration statements are taken from WINWORD.JMS, the
macro file for Microsoft Word for Windows.  Notice that each global variable
name starts with the word, global, so that it can easily be distinguished from
a local variable.  We'll go over naming conventions in more detail in "Macro
Writing Techniques" later in this section.
Globals
        Int GlobalCurrentControl
        Int GlobalRealWindow
        String GlobalWinwordVersion
        String GlobalRealWindowName

The following declaration statements are taken from the Focus Changed macro
in WINWORD.JMS, the macro file for Microsoft Word for Windows.
Remember that this group appears just after the MacroBegin statement.
Var
        Int RealWindow
        Int AppWindow
        String RealWindowName

Global variable may also be declared in an include file as is done with the
default macros and their include file HJGLOBAL.JMH.  Once it is included,
the global variables declared in this file may be used in any of the default
macros.
The following describes how each type is used.

Integer
An integer variable contains a whole number.  We use a variable so that its
value can be changed by actions that take place while our macro file is active
and so that we can refer to the number by name in our macro.

The following rules apply to the use of an integer variable:
  An integer variable must be declared before it can be used.
  It may only contain whole numbers between -32678 and 32767.
  Its default value is always 0.

String
A string variable contains a string of characters.  We use a variable because
the string it contains may be changed by actions that take place while our macro
file is active and so that we can refer to the current string by name in our
macro.

The following rules apply to the use of a string variable:
  A string variable must be declared before it can be used.
  The maximum length of a string variable is 255 characters.
  Its default is always "null" or no characters.

Handle
A handle variable is used to hold a window handle.  You probably remember
from our earlier discussion of window identifiers that the window handle is
assigned by the system and is unique to a particular window.  It is also a
number so you can treat it like any other integer variable.  Most of the time
we use it to identify the window that we want information from.
The following rules apply to the use of a handle variable:
  A handle variable must be declared before it can be used.
  It may only contain whole numbers between -32678 and 32767.
  Its default value is always 0.

Constants
Constants are similar to variables except that their value is set and does not
change.  Think of a constant as a name that is assigned to a number.  There are
no restrictions to how many constant names a number can have.  For example,
in the standard JAWS constants file, the number 1 is assigned the names: True
and On.  What that means is that you can write your macro statement to check
for True or 1.  They are both the same value.  We strongly recommend using
constants because its very difficult to remember that when something is true,
its state is 1, but easy to understand the difference between true and false.

Constants are declared at the beginning of a macro file with the group heading,
Const, as follows:
Const
        True = 1
        False = 0
        On = 1
        Off = 0

Macro writers will sometimes define their own constants for a macro file, but
they often also use those that are already declared in HJCONST.JMH.  We'll go
over those in the next section, "Macro Writing Techniques."

Functions
The JAWS language provides over 200 functions for use in macros.  It would
not be practical to discuss them all here, so we'll be content to discuss the
categories of functions with a brief description of each.  Before we do that,
though, there are a couple of special things about some of the functions that
you must know.

Syntax
The syntax of a function is as follows:
FunctionName()

Parameters
Some functions require parameters.  A parameter is a bit of information that
the function needs to know in order to do its job.  For instance, the function
that gives us the class of a window needs us to tell it which window we are
asking about.

Returns
Some functions provide "returns."  A return is a bit of information that the
function returns back to us.  For instance, our function to get the window class
returns the numeric window class to us.  You might be thinking of window class
as something like "button", but it is actually stored as a number that is then
converted to a name by one of the constants in HJCONST.JMH.

Types of Functions
The functions provided in the JAWS Macro Language may be divided into
groups according to the types of activity they perform.  The following is a list
of functions grouped in this fashion.  You can obtain detailed information on
when and how to use each function from a file in the settings directory called
FUNCTIONS.JML.  You will have to use WordPad to open this file as it is too
large for the JAWS Macro Editor.

Cursor
Use the following functions to activate and position the three cursors available
in JAWS: PC, JAWS, and Invisible.
GetActiveCursor
SayActiveCursor
GetCursorCol
GetCursorRow
SayCursorPos
CaretVisible
SaveCursor
RestoreCursor
InvisibleCursor
RouteInvisibleToJAWS
RouteInvisibleToPc
IsInvisibleCursor
JAWSCursor
RouteJAWSToPc
RouteJAWSToInvisible
IsJAWSCursor
ToggleRestriction
PcCursor
RoutePcToJAWS
IsPCCursor

Positioning
Use the following functions to position a cursor.
MoveTo
MoveToControl
MoveToGraphic
MoveToWindow
JAWSEnd
JAWSHome
JAWSPageDown
JAWSPageUp
PriorCharacter
GetCharacter
NextCharacter
PriorChunk
GetChunk
NextChunk
PriorLine
GetLine
NextLine
PriorWord
GetWord
NextWord
GetField

Say
Use the following functions to speak information either from the screen or
messages within a macro.
Say
SayAll
SayInteger
SayCharacter
SayWord
SpellWord
SayChunk
SayControl
SayField
SayLine
SayToCursor
SayFromCursor
SayTextBetween
SayToBottom
DescribeFont

String
Use the following functions to manipulate strings.
SayString
SpellString
StringContains
SubString
ExpandString

Application
Use the following functions to acquire information about an application.
GetAppFileName
GetAppTitle
GetTreeViewLevel

Braille
Use the following functions to query Braille conditions and displays lines on
the Braille display.
BrailleInUse
PriorBrailleString
BrailleString
NextBrailleString
BraillePanLeft
BraillePanRight
BrailleLine
SixDotBraille
EightDotBraille
GetBrailleMode
SetBrailleMode

Mouse
Use the following functions to move and click the mouse.
MouseUp
MouseDown
MouseLeft
MouseRight
LeftMouseButton
LeftMouseToggle
ShiftLeftMouseClick
AltLeftMouseClick
ControlLeftMouseClick
IsLeftButtonDown
RightMouseButton
RightMouseToggle
IsRightButtonDown

Find
Use the following functions to find specific information on the screen.
FindDialog
FindNext
FindFirstAttribute
FindPriorAttribute
FindNextAttribute
FindLastAttribute
FindGraphic
FindString

Window
Use the following functions to acquire information about windows and to move
from window to window.
GetCurrentWindow
HasTitleBar
GetRealWindow
GetAppMainWindow
GetFirstWindow
GetPriorWindow
GetNextWindow
GetWindowLeft
GetWindowRight
GetParent
IsWindowDisabled
IsWindowObscured
IsWindowVisible
GetFirstChild
GetWindowClass
GetWindowName
GetWindowsOS
GetWindowSubtypeCode
GetWindowType
GetWindowTypeCode
JAWSWindow
MinimizeAllWindows
SayWindow
SayWindowTypeAndText
GetFocus
SetFocus
HasFocusRect
SayFocusRect
SayFocusRects
ActivateMenuBar
DialogActive
GetDialogPageName
IsMultiPageDialog
GetControlID
GetCurrentControlID
GetDefaultButtonName
MenusActive

SDM
The following functions are only used in SDM Dialogs.
SdmGetFocus
SDMGetFirstControl
SDMGetPrevControl
SDMGetNextControl
SDMGetLastControl
SdmSayControl
SdmSayWindowTypeAndText

Speaking Level
The following functions query the verbosity setting and reset it.
GetScreenEcho
ToggleScreenEcho
GetVerbosity
ToggleVerbosity

Options
Use the following functions to get JAWS settings information and change
them.
SetSynth
SetSynthLanguage
SetJawsLanguage
SpeechInUse
GetJcfOption
SetJcfOption
GetDefaultJCFOption
SetDefaultJcfOption
GetHotKey

System Activities
Use the following functions to interact with the system.
MessageBox
PassKeyThrough
PlaySound
Pause
Delay
Refresh
Run

Miscellaneous
The following are functions that do not fit into the other groups.
ActivateStartMenu
Beep
GraphicWizard
IsSameMacroKey
PerformMacroKey
ToggleHomeRow
UnloadJAWS

Operators
The following is a description of the different types of operator which the
JAWS macro language recognizes.

Arithmetic Operators
Arithmetic operators are used with numbers and provide numeric output.  They
are:
+ for addition
- for subtraction
* for multiplication
/ for division.

Relational Operators
Relational operators are used with numbers or strings and compare the value of
the expression before the operator to the expression that follows it.  The
comparisons allowed by the JAWS macro language are:
< checks to see if the expression before this sign is less than the expression
after this sign.
> checks to see if the expression before this sign is greater than the
expression after this sign.
<= checks to see if the expression before this sign is less than or equal
to the expression after this sign.
>= checks to see if the expression before this sign is greater than or
equal to the expression after this sign.
== checks to see if the expression before this sign is equal to the
expression after this sign.
!= checks to see if the expression before this sign is not equal to the
expression after this sign.

Logical Operators
Logical operators are used with numbers or strings to test either or both the
expressions before and after the operator with an expression on the other
side of a relational operator.
|| checks to see if either the expression before this operator or the expression
after it matches a previous relational operator.
&& checks to see if both the expression before this operator and the expression
after it match a previous relational operator.

Negation Operator
The negation operator, NOT, tests to see if the expression before the operator
is not equal to the expression after it.

Assignment Operator
The assignment operator, =, is used to assign a value to a variable.  The
statement looks like this:

MacroBegin {Control+Shift+1}
Var
        Int A
Let A = 1
SayInteger (A)
MacroEnd

In the previous example, the integer variable is assigned a value of 1.

Operator Precedence
It is sometimes important to perform one operation before another when
performing arithmetic or comparisons.  The JAWS macro language provides a
way to insure that things happen in the order you need.  The is done with
parentheses.  The operation inside the parentheses is performed first.  The
operations can be "nested" which means that you can have parenthetical
expressions within other parenthetical expressions.  The innermost operation is
performed first.  Here's an example of what we mean:

MacroBegin {Control+Shift+1}
Var
        Int A
        Int B
        Int C
        Int D
Let A = 1
Let B = 2
Let C = 3
Let D = C + (B - A)
SayInteger( D)
MacroEnd

In the above example the first operation to take place is subtracting A from B,
then the result is added to C and the result of that is assigned to D.  The
answer, of course, is always 4.

Controlling Flow
The flow of statements within a macro is said to be in one of three methods:
*  Sequence - In this method a group of statements are run in order starting at
the beginning and continuing to the end.
*  Selection - In a selection, the flow of activity comes to a "fork in the
road" and must choose one or the other paths.
*  Iteration - An iteration section "loops" (performs the same statement or
group of statements over and over) either while a certain condition is true
or until a certain condition is met.

A macro can contain any or all of these methods.  Let's look at the special
statement structures that cause each of these activities.

Sequence
All of the statements that we have worked with so far are sequence statements.
That means that each of the statements acts in its turn starting at the top of
the macro and continuing to the MacroEnd statement.

Selection
The If statement structure provides a means of selecting one or the other path.
Three statements are required for an If structure:  If, Then and EndIf.  Let's
start with a simple If statement.

If  GetWindowName() == "Main"
Then
   SayString("In the main window.")
EndIf

The function, GetWindowName, used in the If statement returns the title of the
current window.  So what happens is this.  If and only if the name of the
current window is Main, then the SayString function is performed.  Otherwise it
is ignored.  We only take the Then "path" if the condition of the If statement
is true.  There is one optional statement in a If structure, the Else statement.
If an Else statement is added, a second path is provided.

If  GetWindowName() == "Main"
Then
   SayString("In the main window.")
Else
   SayString("Not in the main window.")
EndIf

Now we have an alternative path to travel.  If the window name is Main, we go
down the Then path, otherwise we go down the Else path.
If statements may be nested.  This means that an If statement can be placed
inside of another If statement. Therefore, you can set up to check for a
condition only if another condition exists.

Interation
Remember that an iteration section provides a looping function.
While Loops
A While Loop is a statement sequence that repeats or loops itself while a
particular condition is true.  Let's take a fairly common problem.  You are
working in an editor program that numbers the lines.  Line numbers are 5
digits long.  Therefore, line 1 is listed as 00001. JAWS spends a lot of time
reading the zeros.  It would be nice to start reading at the first non-zero
wouldn't it.  This is a good place to use a while loop.  Consider the following
macro:

MacroBegin {Control+Shift+1}
JAWSCursor()
RouteJAWSToPC()
JAWSHome()
While (GetCharacter () == "0")
   NextCharacter ()
EndWhile
SayFromCursor()
MacroEnd

Using this key would eliminate the zeros for us.
Macro Writing Techniques

Exploring the Application
Before we write a macro file, we must have some idea of what we want to
accomplish with it.  We also often need to explore the windows in our
application to find out what types of things are there and how they should be
read.  One of standard include files, UTILITY.JMH, has macros that may of
some benefit here.  This utility aids in the writing of macros.  Each of the
macros in the utility file is described below.  All of these utility macros are
performed in the Home Row mode (insert + spacebar).

INSERT + H - Lists all of the utilities along with their keystrokes.
F1 - Speaks the requested information (Output Mode) in the current control.
The Output Mode is defined by using the F3 key.  When repeatedly pressing
F3, the Output Mode is cycled in the following order: window handle, control
ID, window class, window type, and first real window name.  When F1 is
pressed twice in quick succession, the requested information is spelled.  Spell
Mode does not apply to integers.
INSERT + F1 - Posts the requested information (Output Mode) to a message
box.  This is not available on Output Modes that return integers.
TAB - Moves the Jaws Cursor to the next window of the same logical level in
the tab list and speaks the required information according to the Output Mode.
SHIFT + TAB - Moves the Jaws Cursor to the prior window of the same logical
level in the tab list and speaks the required information according to the
Output Mode.
F2 - Moves the Jaws Cursor to the first child of the current window and speaks
the required information according to the Output Mode.
SHIFT + F2 - Moves the Jaws Cursor to the Parent of the current window and
speaks the required information according to the Output Mode.
GRAVE ACCENT - Moves the Jaws Cursor to the next requested attribute.
Attributes are defined using the F4 key.  When repeatedly pressing F4, the
attributes are cycled in the following order: bold, italic,    underline,
strikeout, and highlight.
SHIFT + GRAVE ACCENT - Moves the Jaws Cursor to the prior requested
attribute.
CONTROL + GRAVE ACCENT - Moves the Jaws Cursor to the first requested
attribute.
SHIFT + CONTROL + GRAVE ACCENT - Moves the Jaws Cursor to the last
requested attribute.
F3 - Sets the Output Mode.  When repeatedly pressing F3, the Output Mode is
cycled in the following order: SayTypeAndText, window handle, control ID,
window class, window type, and first real window name.
F4 - Sets the Attribute Mode. When repeatedly pressing F4, the attributes are
cycled in the following order: bold, italic, underline, highlight, and strikeout.
P - Reads the Prior Window.  This is useful in determining if the prompt can be
read by reading the prior window.
HOME - Sets the output mode to SayTypeAndText.  The output mode can also
be set to SayTypeAndText by cycling through the modes using F3.

Using these utility macros will help you to get all the information you need
about controls and text attributes to use in your own macros.

Macro File Types
There are several types of macro files and you can tell what type of file
it is by its extension:
.JMS - Source macro files
.JMH - Include files
.JMM - Message files
.JMB - Compiled macro files

Source Files
Source code for macro files is very free-form.  You can place spaces or blank
lines anywhere you like.  Capitalization is not required and is ignored by the
compiler.  Having said that there are a number of formatting things to consider.
While your code may be very easy for you to understand, others may not be able
to make sense of it because they don't know what's in your mind and they may
not organize their work in the same way.  Therefore, we would like to suggest a
few rules of thumb that will make it easier for others to understand your code
and will help you to understand macros written by others.
1. Individual macros should always be separated by a blank line.
2. Indent any section of code that is subservient to that above and below it.
Consider the following macro:

MacroBegin {Control+Shift+1}
If  GetVerbosity() == BEGINNER
Then
   SayString("Beginning verbosity is active.")
Else
   SayString("Beginning verbosity is not active.")
EndIf
MacroEnd

Note that If, Then, Else and EndIf are all at the same indent level and the
statements within each section is indented farther.  How much you indent
is up to you, but we suggest 3 characters.  The JAWS Macro Editor can be
configured so that its tab is 3 characters.  Using tabs to do indents works
better than spaces because indents will be consistent even if in a
proportional font.
3. You may string code statements together.  How you choose to do that is
really up to you.  Some like to have a new line for each statement and some
like to string them together on the same line.  The only convention you
might want to adopt is to keep the line length under 80 characters so that
Braille users can read your code more easily.  Make sure that a complete
statement stays on the same line.
4. Here are a few capitalization suggestions:
   A. Begin each statement with a cap.
   B. Many language function names are the combination of two or more
words that describe the function.  The first character of each word in a
function name is capped.  In the previous example we used
GetVerbosity and SayString.  This helps to have them spoken
correctly, assuming that you have the Mixed Caps option on.  Later on
when you are creating variables, you might want to use the same
convention.
5. The structure of the macro file is also important.
   A. Start each file with a comment that describes what this file contains
and how it is intended to be used.  You might also include a list of
which keys are used and what event macros there are.  Also include a
list of variables and how each is used.  Now someone can read the first
few lines of your file and know all about it.
   B. The next section should be any include statements.
   C. Place any variable declarations in the next section.
   D. Now put in the macros.  The first one should be the AutoStart macro.
Follow this with all the key macros, then the event macros.
6. Comments, comments, comments!  Comments provide a road map for
anyone trying to work with your code.  Place a comment just before each
MacroBegin statement that describes the function of the macro.  Place a
comment in the code describing any complex statement that may not be
intuitive.  Think in terms of someone trying to revise your code and always
give them the help they need.  You will even be helping yourself as you
may forget the purpose of a particular section.

Compiled Files
When you have finished writing your code, it must be compiled for use by the
JAWS program.  Your file must be named the same as the application so that
the JAWS program will know when to load it.  The compilation process is part
of the Macro Editor and we'll cover it there.  For now it is sufficient to say
that your macro file gets compiled before it can be used by JAWS.

Include Files
The JAWS compiler provides for including other files into our macro file at
compile time.  Once the compilation is complete, everything in the included file
is part of our .JMB file and is available whenever our macro file is active.
Files that are meant to be included have the extension .JMH.  Always group your
include statements together near the beginning of your macro file.  Why have
include files and not put everything into our own file?  There are two answers:
organization and efficiency.

Organization
Putting macros with special purposes into separate include files helps to better
organize your work.  Two files are provided with JAWS that contain all of the
standard global variables and constants.  These are HJGLOBAL.JMH and
HJCONST.JMH.  They are provided this way so that macro developers can use any of
the standard variables and constants by simply including them in their own macro
files.  Message files are also set up as includes.  The standard one is
JFW_DESK.JMM.  If you are using a message file, it should be named the same as
your macro file.

Efficiency
There is considerable commonality in many macro files.  You will find that as
you write your macros there will be those that you know would be of use in some
other application.  When you run into those, put them in separate files and then
include them wherever you need them.  It's also useful to have a debug include
file, but we'll cover that in greater detail a little later in the section.

Using Variables
Our earlier section on variables showed you what kind of variables the JAWS
language allows and how to declare them.  In this section we'll discuss when to
use them, suggest some naming conventions and show you where to place them in
your macro files.  Think of a set of variables as a wall with "pigeon holes."
If you are young enough to have never heard of "pigeon holes, " then just
envision little compartments with open fronts.  First we group the compartments
into logical sections and then we name each compartment with a unique name.
Next we place a piece of paper in each with its value.  Remember that the value
can be numeric or a string of characters.  Once the wall is loaded, we can pick
one compartment and change, examine or compare its contents.

Naming Conventions
This is a touchy subject.  Everyone has an opinion and they often conflict.
Regardless of what naming convention you choose, using one will help prevent
time consuming and embarrassing mistakes.  By adopting standards and sticking to
them, you're guaranteeing that you can come back to this code later and modify
or debug with ease.  We in the disability community spend a lot of time talking
about adopting standards.  Here's your chance to contribute.  Having
pontificated on that, let's go over a few suggestions on creating your standard.
What's in a name?  It can be a lot.  Choosing a descriptive name makes a lot of
sense.  The easiest thing to do is to name your variable by putting descriptive
words together.  Try not to make it too long as you have to type the names,
sometimes a lot.  If you are naming a global variable, make the first word of
its name, Global.  You should also cap the beginning of each word as you put
them together so that JAWS can read the words correctly, assuming that you have
the Mixed Case option turned on.

Declaration Placement
Global variables that will be used in more than one macro in your file should be
declared near the beginning of the file.  In fact, we suggest a separate section
with each declaration on its own line.  While you're at it add a comment at the
end of the declaration stating how this variable is used.  Later on you can
refer to this area of the file for information about any variable that you
encounter.  The only time you would declare a variable within a macro is if it
is a local variable and then you should declare it on the next line after the
MacroBegin statement.

Using Global Variables
Remember that variables that you intend to use in more than one macro are
declared as global.  Spend a little time going over the global variables defined
in HJGLOBAL.JMH as they are used a lot in the standard macros.  There are
descriptions of how each is used.  Remember that these variables are often
modified by the standard macros.  Therefore, if you include HJGLOBAL.JMH in your
macro file, you can call upon them to get specific information as needed.  For
instance, checking the contents of GlobalMenuMode will tell you if you are on
the menu bar or in a menu.

Using Constants
Remember that a constant just represents a number so that the statement is
easier to read and understand. You should include the standard constants file,
HJCONST.JMH, in each of your macro files and use the constants in it
whenever you can.  Let's spend a little time going over these constants.  The
file is broken into the following groups:
  Window Type Codes - These codes map to the type of window.  Remember
that even the lowliest control is classified as a window.  Therefore, a
pushbutton will return a window type of 1 or its constant name,
WT_BUTTON.  Consider the following section of code from
JFW_KEY1.JMH.  It is part of the macro that runs when the left arrow key
is pushed.  This else leg of an If, Then, Else statement is run when the left
arrow is pressed and there is no visible PC cursor.  That means that we
want to check to see if we are in some sort of menu.
We've added comments after section of code describing its purpose.

Var
Int TheTypeCode
let TheTypeCode = GetWindowSubTypeCode (GetCurrentWindow())
;This line sets the integer variable, TheTypeCode, to the window type of
the current window.
;Remember that the type code is simply a number, but we will compare it
using constants.
If (TheTypeCode == WT_MENU) then
;This line checks to see if our variable is set to 13 which is the type code
for a menu.  If so the next ;three lines are executed (not killed, just run).
SayString (msg3) ;"Menu"
SayWindow (GetCurrentWindow(), READ_HIGHLIGHTED)
return
;First we say the word, menu.  Then we say whatever text is highlighted, a
good thing to do if we ;have pressed the left arrow key and we are in a
menu.  Lastly, the Return gets us out of this macro as ;we have finished our
task.
EndIf
The EndIf is the formal end to the If, Then, Else statement.
if (TheTypeCode == WT_STARTMENU) then
;If we get here it means that we did not go down the menu leg or else the
Return would have popped ;us out of the macro.  Therefore, we now look to
see if we are in the start menu.
SayString (msg4) ;"Start Menu"
SayWindow (GetCurrentWindow(), READ_HIGHLIGHTED)
return
;Once again, if that were true, then we said start menu followed by the
highlighted item and popped ;out.
EndIf
if (TheTypeCode == WT_CONTEXTMENU) then
;So, we weren't in a menu or the start menu.  Then it might be a context
menu.
SayString (msg5) ;"Context Menu"
SayWindow (GetCurrentWindow(), READ_HIGHLIGHTED)
return
;If we go down this leg, then you know the drill.
EndIf

You may have guessed that this set of constants and their associated
numeric codes are very important to JAWS users as it is from these that we
find out what type of a control we are dealing with.  You may want to
browse this group of constants in HJCONST.JMH  They all start with WT_
for window type.

*  Text Attribute Identifiers - These constants are used for text attribute
comparisons.  They all start with ATTRIB_ for attribute.
*  Commonly Used Constants - These include string and graphic search types
that start with S_, True, False, On and Off.
*  Output Modes - These are not yet implemented.
*  Braille Modes and Marking Types - These all start with BRL_
*  Verbosity Settings - These are BEGINNER, INTERMEDIATE AND
ADVANCED.
*  General - These include testing for active and success, cursors, various
reading settings, and option settings.
*  Cursor Types - This is what you get for various cursor shapes.  Remember
that the mouse is a cursor and if  you get CT_Wait back, the hour glass is
visible.  These are not yet implemented for Windows 95.
*  The Rest - Finally we have the constants used for menu status, operating
system and the current default file.

Using Functions
Stringing Functions Together
Sometimes you have to use a number of functions together to achieve your goal.
If fact, sometimes one function becomes the parameter for another, which is the
parameter for yet another.  This can look rather confusing in the code.  The
trick is to count up the parentheses.  They will show you the nesting of
functions into other functions.  The innermost nested function is followed by ().
First we'll look at a group of functions strung together for a single purpose
and then we'll look at complex functions.
It's pretty rare when you can accomplish a task with a single function.  Several
functions in the proper order are usually required.  The following code is from
a macro file for Visual Basic 4.0.  It's job is to check whether the Toolbox is
the focus window and, if not, make it so and then position the JAWS cursor on
the first tool icon..  By the way, we used the utility macros to figure out the
window class of the tool box window before we wrote this macro.

; This macro focuses on the tool box and positions the JAWS cursor
; at the top, right tool of the tool box
MacroBegin {CTRL+SHIFT+F1}
SayString ("Tool Box") ; Let the user know what's happening
While GetScreenEcho() != 2 ; Loop through the screen echo settings until we
   set say all
   ToggleScreenEcho ()          ; Set say all
EndWhile
If GetWindowClass (GetFocus ()) != "ToolsPalette"  ; Are we already in the
tool box
Then ; We are not
   PcCursor();
   {alt+v} ; View Menu
   Pause() ; Time for the menu to appear
   {x};      ; Select Tool Box
EndIf
Delay(10)             ; Time for tool box to appear
RouteJawsToPc()
JAWSCursor()
JawsPageUp()
JawsHome()
PerformMacroKey ({DOWN ARROW}) ; Regular down arrow with special
stuff for the tool box
MacroEnd

*  First we make sure we are in say all screen echo mode.
*  Next we check to see if we are not in the ToolBox by getting the window
class of the current focus window and comparing it to the string,
ToolsPalette, which is the known window class of the ToolBox window.  If
we are not in the ToolBox, then we must make that the focus window by
performing several functions that will guarantee the end result.
*  We use the PcCursor function to force the PC cursor active.
*  We use the keyboard function to send an Alt+V to the application.  This
pulls down the View menu.  Note that there is a comment there to let
anyone reading this know that that's the purpose of Alt+V.
*  The Pause function then gives the system time to pull down the menu
before we continue.
*  We use the keyboard function to send an X to the application which is the
shortcut key for the ToolBox menu item.  This is also commented.
*  Then the EndIf to close out our If statement sequence.
*  Now we are sure the ToolBox is open and has the focus.
*  Then we activate the JAWS cursor and position it on the first tool icon.

We've used a number of functions strung together to accomplish our task.

Writing Complex Functions
Here is an example of a macro with a complex function in which one function
is the parameter of another.

MacroBegin {Control+Shift+1}
If (GetWindowClass (GetAppMainWindow (GetFocus())) == wc112)
Then
   SayString (msg113) ;"This is the JAWS application window"
EndIf
MacroEnd

We know that the window class of the JAWS window is WC112, so we want to
compare our window class to that, but first we must make sure that we are
looking at the correct place.  We use the function, GetWindowClass to query a
window class.  Its parameter is a window handle, so we give it
AppMainWindow which is the parent in the current application.
AppMainWindow requires a window handle as its parameter.  That is which
application main window.  In our case we use the function, GetFocus, which
returns the window handle of the focus window.  Simply said it is: get the
window class of the application window that is in focus.

Selecting and Manipulating Cursors
Before you attempt to read something from the screen with a macro, it's
important to understand about cursors.  Just from using JAWS you know that
there are two kinds of cursor: PC and JAWS.  The PC cursor is usually where
characters would be placed when you type.  However, when you are using a
menu or tabbing through some selections, think of the PC cursor as the "visual
focus."  We spend most of our time using PC cursor, but you know that when
you need to read other areas of a window, you switch to JAWS cursor.  When
we use the JAWS cursor, it is not restricted and can go anywhere and read any
text on the screen.  You probably also know that the JAWS cursor always
moves the mouse pointer along with it.  There is actually a third kind of cursor
called the Invisible cursor.  It is just like the JAWS cursor as its movement is
not restricted, but it does not bring the mouse pointer with it.  What do we do
with these cursors and why?

The PC cursor belongs to our computer and so we should not be moving it around
with a macro.  There are also many places on the screen where the PC cursor
cannot go like the title of a window or the status bar.  Therefore, before we go
to read some text from the screen, we should first switch to one of the other
cursors, but which one?  Here's a rule of thumb.  If we plan to stay at the new
position and read around, then we should use the JAWS cursor.  Then all of the
JAWS cursor commands are available and we can click with the mouse.  If our goal
is to go read something and return to the present position, then use the
invisible cursor.  There is also a save and restore function that you can use to
put everything back as it was before our macro.

Here is a list of the functions that you can use to select and manipulate the
cursors:
PcCursor() - Activates the PC Cursor.
JAWSCursor() - Activates the JAWS Cursor.
InvisibleCursor() - Activates the Invisible Cursor.
RoutePCtoJAWS() - Moves the PC Cursor to the JAWS Cursor, if possible.
RouteJAWStoPC() - Moves the JAWS Cursor to the PC Cursor.
RouteJAWSto Invisible() - Moves the JAWS Cursor to the Invisible Cursor.
RouteInvisibletoPC() - Moves the Invisible Cursor to the PC Cursor.
RouteInvisibletoJAWS() - Moves the Invisible Cursor to the JAWS Cursor.
SaveCursor() - Remembers the active cursor and its position.
RestoreCursor() - Reactivates the saved cursor and position.

The next group of functions move the cursor.
PriorCharacter() - Moves the active cursor to the prior character.
PriorWord() - Moves the active cursor to the prior word.
PriorLine() - Moves the active cursor to the prior line.
NextCharacter() - Moves the active cursor to the next character.
NextWord() - Moves the active cursor to the next word.
NextLine() - Moves the active cursor to the next line.
JAWSHome() - Moves the active cursor to the beginning of the line.
JAWSEnd() - Moves the active cursor to the end of the line.
JAWSPageUp() - Moves the active cursor to the top of the window.
JAWSPageDown() - Moves the active cursor to the bottom of the window.
Note that you would usually follow a move function with a read function.

Here is an example of saving the current cursor, switching cursors, moving the
cursor, reading some text and then returning to the original position with the
original cursor:

MacroBegin {Insert+Page Down}
Var
   Int TheTypeCode
Let TheTypeCode = GetWindowSubTypeCode (GetCurrentWindow())
SaveCursor() ; Save the current cursor and position
InvisibleCursor() ; Switch to invisible cursor
RouteInvisibleToPC() ; Bring the invisible cursor to the PC cursor
If (TheTypeCode == WT_MENU) ; Are we in a menu
Then
   MoveToWindow (GetAppMainWindow (GetCurrentWindow())) ; Refocus
   ; on the main window
   JAWSPageDown () ; Go to the bottom
   JAWSHome() ; Go to the left
   NextWord() ; Move one word to the right
   SayChunk() ; Says the chunk of text that was written to the screen together
Else
   JAWSPageDown() ; Go to the bottom
   SayLine() ; Say the line
Endif
RestoreCursor() ; Go back to the original cursor and position
MacroEnd

This is the macro that reads the bottom line of a window.  Usually this is where
the status bar is located.  The PC cursor is not allowed to go to this location,
so we must switch to Invisible cursor and use it to read this line.  Notice that
there is a SaveCursor function before taking this action and a RestoreCursor
function after.  That way, everything is the same as before after reading the
status bar.

Using the JAWS Macro Editor
You create and edit macro files with the JAWS Macro Editor.  It has some very
slick built-in features that make macro writing much simpler.  The JAWS
Macro Editor is a full-function Windows editor and is capable of editing
multiple files simultaneously, each in their own separate window.  It has all of
the usual editing functions along with a few very special ones that make macro
writing much easier.  We'll leave you to explore all of the menu items on its
menu bar, but we will point out those special macro writing tools.  Start the
editor.

The Macro Menu
Most of the macro tools are on this menu.  You can open the Macro pull-down
menu by either moving to the menu bar with the Alt key and then using arrow
keys or you can press Alt+M, which is the shortcut key.  If you are using the
Laptop Key layout, you cannot use Alt+M as it is a JAWS key.
*  Add Macro - The first item is Add Macro and what it does is to go to the
end of the current macro, add the MacroBegin and MacroEnd statements
with a blank line in between and position the cursor in between the braces
in the MacroBegin statement so that you can type in the name of your
macro.  Note that the shortcut key is Control+A.  This is one you will want
to remember.
*  Insert Function - This item opens the Insert Function dialog.  We'll leave
the discussion of the Insert Function dialog until after we go through the
rest of the menus.  The only thing to remember for now is that the shortcut
key is Control+I.
*  Compile Macro - This item compiles the macro in the current window.  Its
shortcut key is Control+M.
*  Next Macro - Next Macro moves the cursor to the next macro, highlights
the name (the name is in between the braces) and places the cursor at the
end of the name.  That way, JAWS announces the name of each macro as
you move through them with this item's shortcut key, F2.
*  Previous Macro - This menu item performs the same action as the Next
Macro item except that it moves to the previous macro.  Its shortcut key is
Shift+F2.
*  Go To Line - As you might suspect, this item is used to focus on a specific
line number in the current macro file.

Window Menu
The window menu lists all the files that the editor has open and can be used to
make one of them the focus window or you can simply press Control+Tab to
move to the next file in the ring and, of course, Shift+Control+Tab to go
through the ring backwards.

Using the Function Insertion Tool
Selecting Insert Function from the Macro menu or pressing Control+I opens the
Insert Function dialog.  This dialog has a field for the function name, a list
box with all the JAWS functions preloaded into it and some push buttons.  It
also has an area of static text that describes the current highlighted function.

Choosing a Function
When the cursor is in the Function Name field as it is when the dialog is
opened, you can start typing the name of a function.  The list of functions is
searched for matches as you type.  Usually the first four characters is all you
need to find the one you want.  The static help text is read as each new
function is highlighted.  If you don't know the name of the function or if you
just want to browse through them, tab to the list box and then use the arrow
keys.  You can also press the first letter of a function while you are in the
list box and the highlight is moved to the first function that starts with that
letter.  The default button in this window is the Next button.  After you find
the function you want, just press enter.

Adding Parameters
Some functions require parameters in order to work correctly.  Don't worry, the
editor knows which ones and what parameters are required.  You might
remember from our first macro earlier that we had to pass a parameter to the
SayString function.  We did it the hard way then, but now let's look at writing
that macro the easy way.  If you are in the Insert Function dialog, press Escape
to return to the editor window.
Creating a Macro The Easy Way
Use the following steps to create the same macro that we did in our first macro,
but this time we'll let the editor do some of the work for us.
1. You should be in the editor with an empty file.  If not, open the editor and
press Control+N to start a new file.
2. Start a new macro by pressing Control+A.
3. Your cursor is between the brackets, so type Control+Shift+A and press
down arrow to move to the blank line.
4. Press Control+I to open the Insert Function dialog.
5. Your cursor is in the Function Name field, so type SAYS and you should
hear SayString along with a description of this function.
6. Press Enter to select this function and move on to the next window where
we will type in the required parameter.
7. You are in the field where the parameter goes and should have heard a
description of the parameter required.  We just want a string spoken, so
type "My name is Frank" or whatever your name is.  Don't forget to put it
within quotes.
8. Press Enter to select the Next button.  This time the Insert Function dialog
knows that we are done so it closes the dialog, places our statement into the
editor window and positions our cursor at the end of the line.
Note that we used the Next button exclusively.  This is a good idea as this
button always takes you to the next item that needs to be entered.  The
Next button automatically inserts the function when it is complete.  You
can always override this with the Finish button, but using the Next button
helps to prevent missing parameters. Pressing Finish tells the dialog to
place whatever function was selected into the file.  Then you have to type
in your own parameters.

Browse the lines and see that we have just created a macro the easy way.  Use
the editor to create a few more macros using various functions just to get used
to how the process works before you move on.

Debugging
Volumes have been written about debugging programs.  The most important thing to
remember is that it takes a different mind set than normal diagnostics.
Diagnosing a problem usually starts with the assumption that whatever you are
working on was once working and is now broken.  Therefore, if you simply follow
the logical flow from start to finish, you will find the errant part.  Debugging
something that hasn't worked yet means that you cannot assume that even the flow
is correct.  How does this relate to debugging our macro file?  It's simple.  Do
not assume that just because you intended for the flow to be a certain way, that
it will be.  JAWS may not always think the same way you do or, heaven forbid,
you may have left out a little piece.  Having said that, there are a lot of
different things that can help you in this debugging effort.

The JAWS Compiler
The first big help is the compiler.  It checks the syntax of your commands and
statements and also makes sure that you complete each sequence correctly.  It
displays an error message when you try to compile a macro with a mistake in it.
You might find the error messages a bit hard to understand at first, but try to
think like a compiler.  Let's look at a typical example.  We'll use an example
from a previous section that checks on the current  window name, but we've left
something out.

MacroBegin{Shift+Control+F1}
If  GetWindowName() == "Main"
Then
   SayString("In the main window.")
Else
   SayString("Not in the main window.")
MacroEnd

You probably noticed that we left out the EndIf.  When we try to compile this
macro, we get the error, "Syntax error. Found unexpected word MacroEnd."
Why didn't it just say that we left out the EndIf?  The JAWS compiler is linear.
It starts at the beginning of the file and goes through it one line at a time.
Here's the pattern:
1. Found an If statement and it had a valid function after it.
2. Found a Then statement and it had a valid function after it.
3. Found an Else statement and it had a valid function after it, but it also had
a MacroEnd command after it.  A MacroEnd command can only occur
when nothing else is active.  The compiler knows that's it is not valid here,
so it displays a message saying it found something wrong, an unexpected
word in the else statement.
By the way, after you click OK in the error message box, the editor places the
cursor at the spot where the error occurred so that you can fix it.

Include files are examined as they are included.  Always place the include
statement in your macro file before you use anything in the include file.  For
instance, you must include HJCONST.JMH before using any of the constants in
it.  Of course, if you are following the rules we set out earlier, all of your
includes are at the beginning of your macro file anyway.

Erroneous Activity
Once your macro file compiles without error, it's time to test it in its
intended environment.  Here are a few tips to make this process easier:
*  Fragments - Whenever possible, compile fragments separately and test to
see if they work by themselves.
*  Messages may be inserted at crucial points in the code so that JAWS tells
you what it's doing.  For instance, SayString messages in each leg of an If,
Then, Else statement will inform you of which leg was executed.
*  Many errors of operation can be traced to the failure to save and restore
states.  Anytime you have to change a state for your purposes, be sure to
return to the original state.  For instance, changing to SayAll so that you
can hear a help bubble spoken is fine, but don't leave the user there as it
will be very confusing.
*  Debug Macros - You can create debug macros that report all sorts of stuff
like which cursor  is active, what's contained in variables and various
window properties.  Here are a couple of macros that you can copy and
paste into your macro file and modify to report information back to you.

MacroBegin {Control+Shift+F1}
SayString( MyVariable) ; Fill in the name of your variable
; Copy the preceding line for each of your variables
MacroEnd

MacroBegin {Control+Shift+F2}
SayString( GetWindowClass (GetFocus ())) ; Window class of focus control
SayString ( GetWindowClass (GetParent (GetFocus ()))) ; Window class of
        ;the parent
PerformMacroKey( {Control+Insert+Shift+F1}) ; Control name
MacroEnd
